// 不借助JavaScript this绑定的相关API实现一个apply和call

interface Function {
  myApply(context: any, args: any[]): any;
  myCall(context: any, ...args: any[]): any;
}
Function.prototype.myApply = function(context: any, args: any[]) {
  let tempKey = Symbol(); // 声明一个独一无二的属性防止现有的key被覆盖
  context = context || undefined; // 严格模式下上下文如果没给就指向undefined
  args = args || [];
  context[tempKey] = this; // this会指向当前的函数，将它赋值给上下文对象的某一属性以实现this的隐式绑定
  const res = context[tempKey](...args); // 解构参数并调用方法，this已经隐式绑定在上下文对象上
  delete context[tempKey];  // 释放临时的Symbol属性
  return res;
};
Function.prototype.myCall = function(context: any, ...args: any[]) {
  let tempKey = Symbol(); // 声明一个独一无二的属性防止现有的key被覆盖
  context = context || undefined; // 严格模式下上下文如果没给就指向undefined
  args = args || [];
  context[tempKey] = this; // this会指向当前的函数，将它赋值给上下文对象的某一属性以实现this的隐式绑定
  const res = context[tempKey](...args); // 解构参数并调用方法，this已经隐式绑定在上下文对象上
  delete context[tempKey]; // 释放临时的Symbol属性
  return res;
};



// 测试用例
const o1 = {
    name: 'joy',
    getName(args:any) {
        console.log(this); 
        console.log(this.name,args); 
    }
};
const o2 = {
    name: 'sam'
};
o1.getName.myCall(o2,123,456); // obj2 sam
o1.getName.myApply(o2,[123,456,789]); // obj2 sam